#include "sudoku_field.h"
//------------------------------------------------------------------------------------------------------------
SudokuField::SudokuField(int pid, vector<int>* pinitialAvailableValues)
	: id(pid), initialAvailableValues(pinitialAvailableValues)
{
    //value = availableValues.begin();
}
//------------------------------------------------------------------------------------------------------------
SudokuFieldOrder::SudokuFieldOrder(int id, vector<int>* pinitialAvailableValues)
	: SudokuField(id, pinitialAvailableValues)
{
	ordering = *initialAvailableValues;
	//vector<int>* d;
	availableValues = new set < int, ValuesCmp < vector < int > * > > (&ordering);
    initAvailableSet();
	value = availableValues->begin();
}
//------------------------------------------------------------------------------------------------------------
SudokuFieldRandom::SudokuFieldRandom(int id, vector<int>* pinitialAvailableValues)
	: SudokuField(id, pinitialAvailableValues)
{
	ordering = *initialAvailableValues; //zrandomizować !
	randVector(ordering);
	//int tab[] = {0,7,4,8,3,9,2,5,6,1};
	//int tab[] = {1,2,3,4,5,6,7,8,9};
	//int tab1[10];
	//tab1[0] = 0;
	//randPerm(tab + 1, tab1 + 1, 9);
	//cout << "pinitialAvailableValues->size()=" << pinitialAvailableValues->size() << " sizeof(tab)/sizeof(int)="<<sizeof(tab)/sizeof(int) << endl;
	//ordering.resize(pinitialAvailableValues->size());
	
	//ordering.resize(sizeof(tab)/sizeof(int) + 1);
	//std::copy(tab1, tab1 + sizeof(tab)/sizeof(int), ordering.begin());
	
	//ordering[0] = 0;
	//std::copy(tab, tab + sizeof(tab)/sizeof(int), ordering.begin() );
	//for(int i = 0; i < 10; i++)
		//ordering[i] = tab[i];
	
	/*
	cout << "ordering["<<id<<"]: ";
	BOOST_FOREACH(int v, ordering)
	{
		cout << v << " ";
	}
	cout << endl;
	*/
	
	availableValues = new set<int, ValuesCmp<vector<int>* > > (&ordering);
    initAvailableSet();
    value = availableValues->begin();
}
//------------------------------------------------------------------------------------------------------------
void SudokuFieldRandom::randVector(vector<int>& v)
{
	std::vector<int> t;
	for(vector<int>::iterator it = v.begin() + 1; it != v.end(); it++)
	{
		t.push_back(*it);
	}
	for(int i = 1; i < v.size(); i++)
	{
		int s = t.size();
		int r = (rand() % t.size());
		v[i] = t[r];
		//cout << "size()=" << t.size() << " r=" << r << endl;
		t.erase(t.begin() + r);
	}
}
//------------------------------------------------------------------------------------------------------------
void SudokuField::initAvailableSet()
{
	//cout << "[ENTER]SudokuField::initAvailableSet()\n";
    std::set<int>::iterator it = availableValues->begin();
    std::copy(initialAvailableValues->begin(),
              initialAvailableValues->end(),
              std::inserter(*availableValues, it));
	//randomizeAvailableValues(initialAvailableValues, availableValues);
    //cout << "[EXIT]SudokuField::initAvailableSet()\n";
}
//------------------------------------------------------------------------------------------------------------
/*
void SudokuFieldRandom::initAvailableSet()
{
	cout << "[ENTER]SudokuFieldRandom::initAvailableSet()\n";
    std::unordered_set<int>::iterator it = availableValues.begin();
    std::copy(initialAvailableValues.begin(),
              initialAvailableValues.end(),
              std::inserter(availableValues, it));
	//randomizeAvailableValues(initialAvailableValues, availableValues);
    cout << "[EXIT]SudokuFieldRandom::initAvailableSet()\n";
}
*/
//------------------------------------------------------------------------------------------------------------
/*
void SudokuField::initAvailableSet()
{
	cout << "[ENTER]SudokuField::initAvailableSet()\n";
    std::unordered_set<int>::iterator it = availableValues.begin();
    std::copy(initialAvailableValues.begin(),
              initialAvailableValues.end(),
              std::inserter(availableValues, it));

    /*
    for(; it != initialAvailableValues.end(); it++)
    {
        availableValues.insert(*it);
    }

    //availableValues.insert(*(initialAvailableValues.begin()));
	cout << "[EXIT]SudokuField::initAvailableSet()\n";
}
*/
//------------------------------------------------------------------------------------------------------------
void SudokuField::print() const
{
    //std::cout << "[ENTER]\tSudokuField::print\n";

    std::cout << "field[" << id << "]\t";

    BOOST_FOREACH(int iav, *initialAvailableValues)
    {
        cout << iav << " ";
    }
    std::cout << " : ";


    BOOST_FOREACH(int av, *availableValues)
    {
        std::cout << av << " ";
    }

    std::cout << " : " << *value << std::endl;
    //std::cout << "[EXIT]\tSudokuField::print\n";
}
//------------------------------------------------------------------------------------------------------------
/*
void SudokuFieldRandom::randomizeAvailableValues(vector<int>* src, vector<int>* dest)
{
	int *c, s, r, i, j;

	s = src->size();
	c = new int[s];
	for(i = 0; i < s; i++)
		c[i] = 0;

	while(s > 0)
	{
		r = rand() % s;

		j = 0; i = 0;
		while(j <= r)
		{
			if(c[i] == 0)
				j++;
			i++;
		}
		cout << "r=" << r << " s=" << s << " i=" << i << " j=" << j << endl;
		//*dest[s-1] = *src[i-1];
		dest->push_back((*(src))[i-1]);
		c[i-1] = 1;
		s--;
	}

	//delete[] c;
}
*/
//------------------------------------------------------------------------------------------------------------
